home *** CD-ROM | disk | FTP | other *** search
/ GameStar 2004 April / Gamestar_61_2004-04_dvdb.iso / DVDStar / Editace / hltp.exe / {app} / Source Code / VirtualDub / disasm / main.cpp < prev    next >
C/C++ Source or Header  |  2003-10-01  |  29KB  |  1,090 lines

  1. //    disasm - Disassembly module compiler for VirtualDub
  2. //    Copyright (C) 2002 Avery Lee, All Rights Reserved
  3. //
  4. //    This program is free software; you can redistribute it and/or modify
  5. //    it under the terms of the GNU General Public License as published by
  6. //    the Free Software Foundation; either version 2 of the License, or
  7. //    (at your option) any later version.
  8. //
  9. //    This program is distributed in the hope that it will be useful,
  10. //    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. //    GNU General Public License for more details.
  13. //
  14. //    You should have received a copy of the GNU General Public License
  15. //    along with this program; if not, write to the Free Software
  16. //    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  
  18. #pragma warning(disable: 4786)
  19.  
  20. #include <string>
  21. #include <list>
  22. #include <vector>
  23. #include <utility>
  24. #include <algorithm>
  25.  
  26. #include <stdio.h>
  27. #include <string.h>
  28. #include <stdarg.h>
  29. #include <ctype.h>
  30. #include <conio.h>
  31.  
  32. void strtrim(char *s) {
  33.     char *t = s;
  34.     char *u = s;
  35.  
  36.     while(*t)
  37.         ++t;
  38.  
  39.     while(t>s && isspace((unsigned char)t[-1]))
  40.         --t;
  41.  
  42.     while(u<t && isspace((unsigned char)*u))
  43.         ++u;
  44.  
  45.     memmove(s, u, t-u);
  46.     s[t-u] = 0;
  47. }
  48.  
  49. char *strtack(char *s, const char *t) {
  50.     while(*s = *t)
  51.         ++s, ++t;
  52.  
  53.     return s;
  54. }
  55.  
  56. typedef unsigned char byte;
  57.  
  58. struct rule {
  59.     std::vector<std::pair<byte, byte> > match_stream;
  60.     std::string result;
  61.     std::string    rule_line;
  62.     int argcount;
  63. };
  64.  
  65. struct ruleset {
  66.     std::list<rule>        rules;
  67.     std::string            name;
  68. };
  69.  
  70. typedef std::list<ruleset>                tRuleSystem;
  71. tRuleSystem        g_RuleSystem;
  72.  
  73. void oops(const char *format, ...) {
  74.     va_list val;
  75.  
  76.     va_start(val, format);
  77.     vprintf(format, val);
  78.     va_end(val);
  79.     getch();
  80.     exit(5);
  81. }
  82.  
  83.  
  84. // 1-15 are static lookups
  85. static const char kTarget_r32        = 1;
  86. static const char kTarget_r16        = 2;
  87. static const char kTarget_r8        = 3;
  88. static const char kTarget_rm        = 4;
  89. static const char kTarget_rx        = 5;
  90. static const char kTarget_rc        = 6;
  91. static const char kTarget_rd        = 7;
  92. static const char kTarget_rs        = 8;
  93. static const char kTarget_rf        = 9;
  94.  
  95. // 16-31 are dynamic translations
  96. static const char kTarget_r1632        = 16;
  97. static const char kTarget_rmx        = 17;
  98. static const char kTarget_x            = 18;
  99. static const char kTarget_hx        = 19;
  100. static const char kTarget_lx        = 20;
  101. static const char kTarget_s            = 21;
  102. static const char kTarget_o            = 22;
  103. static const char kTarget_ho        = 23;
  104. static const char kTarget_lo        = 24;
  105. static const char kTarget_a            = 25;
  106. static const char kTarget_ha        = 26;
  107. static const char kTarget_la        = 27;
  108.  
  109. static const char kTarget_ap        = (char)224;
  110. static const char kTarget_p_cs        = (char)225;
  111. static const char kTarget_p_ss        = (char)226;
  112. static const char kTarget_p_ds        = (char)227;
  113. static const char kTarget_p_es        = (char)228;
  114. static const char kTarget_p_fs        = (char)229;
  115. static const char kTarget_p_gs        = (char)230;
  116. static const char kTarget_p_66        = (char)231;
  117. static const char kTarget_p_67        = (char)232;
  118. static const char kTarget_p_F2        = (char)233;
  119. static const char kTarget_p_F3        = (char)234;
  120.  
  121.  
  122. void parse_ia(FILE *f) {
  123.     char linebuf[4096];
  124.     ruleset        *pRuleset = NULL;
  125.  
  126.     while(fgets(linebuf, sizeof linebuf, f)) {
  127.         strtrim(linebuf);
  128.  
  129.         if (!linebuf[0] || linebuf[0] == '#')
  130.             continue;
  131.  
  132.         puts(linebuf);
  133.  
  134.         if (linebuf[0] == '%') {            // ruleset definition
  135.             strtrim(linebuf+1);
  136.  
  137.             ruleset r;
  138.             r.name = linebuf+1;
  139.             g_RuleSystem.push_back(r);
  140.             pRuleset = &g_RuleSystem.back();
  141.         } else {                            // rule definition
  142.  
  143.             if (!pRuleset)
  144.                 oops("Not in ruleset:\n>%s\n", linebuf);
  145.  
  146.             rule r;
  147.  
  148.             r.rule_line = linebuf;
  149.             r.argcount = 0;
  150.  
  151.             // Find colon
  152.  
  153.             char *colon = linebuf;
  154.  
  155.             while(*colon != ':') {
  156.                 if (!*colon)
  157.                     oops("Colon missing in rule:\n>%s\n", linebuf);
  158.  
  159.                 ++colon;
  160.             }
  161.  
  162.             // Nuke colon
  163.  
  164.             *colon++ = 0;
  165.  
  166.             // Parse tokens until colon is found
  167.  
  168.             static const char whitespace[]=" \t\n\v";
  169.             const char *token = strtok(linebuf, whitespace);
  170.  
  171.             std::vector<bool> argumentTypeStack;        // true if arg is a string
  172.  
  173.             if (token) do {
  174.                 if (*token == '*') {                        // any character
  175.                     if (!r.match_stream.empty() && !r.match_stream.rbegin()->second && r.match_stream.rbegin()->first < 15)
  176.                         ++r.match_stream.rbegin()->first;
  177.                     else {
  178.                         r.match_stream.push_back(std::pair<byte, byte>(1,0));
  179.                     }
  180.  
  181.                     argumentTypeStack.push_back(false);
  182.                     ++r.argcount;
  183.                 } else if (*token == '[') {
  184.                     if (!strcmp(token+1, "66]"))
  185.                         r.match_stream.push_back(std::pair<byte, byte>(16,0));
  186.                     else if (!strcmp(token+1, "67]"))
  187.                         r.match_stream.push_back(std::pair<byte, byte>(17,0));
  188.                     else if (!strcmp(token+1, "F2]"))
  189.                         r.match_stream.push_back(std::pair<byte, byte>(18,0));
  190.                     else if (!strcmp(token+1, "F3]"))
  191.                         r.match_stream.push_back(std::pair<byte, byte>(19,0));
  192.                     else if (!strcmp(token+1, "!s]"))
  193.                         r.match_stream.push_back(std::pair<byte, byte>(20,0));
  194.                     else
  195.                         oops("unknown prefix match token '%s'\n", token);
  196.                 } else if (isxdigit((unsigned char)token[0]) && isxdigit((unsigned char)token[1])
  197.                         && (token[2] == '-' || !token[2])) {        // match character
  198.                     int byteval, byteend;
  199.                     int c;
  200.  
  201.                     c = sscanf(token, "%x-%x", &byteval, &byteend);
  202.  
  203.                     if (byteval < 0 || byteval >= 256)
  204.                         oops("byte start value out of range\n");
  205.  
  206.                     if (c<2) {
  207.                         byteend = byteval;
  208.                     } else if (byteend != byteval) {
  209.                         if (byteend < 0 || byteend >= 256)
  210.                             oops("byte end value out of range\n");
  211.                     }
  212.  
  213.                     r.match_stream.push_back(std::pair<byte, byte>(byteval, ~(byteval ^ byteend)));
  214.                     argumentTypeStack.push_back(false);
  215.                     ++r.argcount;
  216.  
  217.                 } else {                                    // macro invocation
  218.                     tRuleSystem::iterator it = g_RuleSystem.begin();
  219.                     tRuleSystem::iterator itEnd = g_RuleSystem.end();
  220.                     int index = 128;
  221.  
  222.                     if (*token == '!') {    // reuse last byte char
  223.                         index = 192;
  224.                         ++token;
  225.                     }
  226.  
  227.                     for(; it!=itEnd; ++it, ++index) {
  228.                         if (!stricmp((*it).name.c_str(), token))
  229.                             break;
  230.                     }
  231.  
  232.                     if (it == itEnd)
  233.                         oops("unknown ruleset '%s'\n", token);
  234.  
  235.                     r.match_stream.push_back(std::pair<byte, byte>(index, 0));
  236.                     r.argcount += 2;
  237.                     argumentTypeStack.push_back(false);
  238.                     argumentTypeStack.push_back(true);
  239.                 }
  240.             } while(token = strtok(NULL, whitespace));
  241.  
  242.             // match sequence parsed -- parse the result string.
  243.  
  244.             char *s = colon;
  245.  
  246.             for(;;) {
  247.                 while(*s && strchr(whitespace, *s))
  248.                     ++s;
  249.  
  250.                 if (!*s || *s == '#')
  251.                     break;
  252.  
  253.                 if (*s == '"') {    // string literal
  254.                     const char *start = ++s;
  255.  
  256.                     while(*s != '"') {
  257.                         if (!*s)
  258.                             oops("unterminated string constant\n");
  259.  
  260.                         ++s;
  261.                     }
  262.                     
  263.                     r.result.append(start, s-start);
  264.                     ++s;
  265.                 } else if (*s == '$') {    // macro expansion
  266.                     ++s;
  267.  
  268.                     if (!strnicmp(s, "p_cs", 4)) {
  269.                         r.result += kTarget_p_cs;
  270.                         s += 4;
  271.                     } else if (!strnicmp(s, "p_ss", 4)) {
  272.                         r.result += kTarget_p_ss;
  273.                         s += 4;
  274.                     } else if (!strnicmp(s, "p_ds", 4)) {
  275.                         r.result += kTarget_p_ds;
  276.                         s += 4;
  277.                     } else if (!strnicmp(s, "p_es", 4)) {
  278.                         r.result += kTarget_p_es;
  279.                         s += 4;
  280.                     } else if (!strnicmp(s, "p_fs", 4)) {
  281.                         r.result += kTarget_p_fs;
  282.                         s += 4;
  283.                     } else if (!strnicmp(s, "p_gs", 4)) {
  284.                         r.result += kTarget_p_gs;
  285.                         s += 4;
  286.                     } else if (!strnicmp(s, "p_66", 4)) {
  287.                         r.result += kTarget_p_66;
  288.                         s += 4;
  289.                     } else if (!strnicmp(s, "p_67", 4)) {
  290.                         r.result += kTarget_p_67;
  291.                         s += 4;
  292.                     } else if (!strnicmp(s, "p_F2", 4)) {
  293.                         r.result += kTarget_p_F2;
  294.                         s += 4;
  295.                     } else if (!strnicmp(s, "p_F3", 4)) {
  296.                         r.result += kTarget_p_F3;
  297.                         s += 4;
  298.                     } else if (!strnicmp(s, "ap", 2)) {
  299.                         r.result += kTarget_ap;
  300.                         s += 2;
  301.                     } else {
  302.                         unsigned long id = strtoul(s, &s, 10);
  303.  
  304.                         if (!id || id > r.argcount)
  305.                             oops("macro argument $%lu out of range\n", id);
  306.  
  307.                         if (!r.result.empty() && *r.result.rbegin() == ' ')
  308.                             *r.result.rbegin() = (char)(id + 0x80);
  309.                         else
  310.                             r.result += (char)id;
  311.  
  312.                         int firstbit = 0;
  313.                         int lastbit = 7;
  314.  
  315.                         if (*s == '[') {
  316.                             ++s;
  317.  
  318.                             firstbit = strtol(s, &s, 10);
  319.  
  320.                             if (*s++ != '-')
  321.                                 oops("macro argument bitfield range missing '-'\n");
  322.  
  323.                             lastbit = strtol(s, &s, 10);
  324.  
  325.                             if (firstbit < 0 || lastbit > 7 || firstbit > lastbit)
  326.                                 oops("invalid bitfield %d-%d\n", firstbit, lastbit);
  327.  
  328.                             if (*s++ != ']')
  329.                                 oops("invalid bitfield\n");
  330.                         }
  331.  
  332.                         if (!*s)
  333.                             oops("macro expansion missing format\n");
  334.  
  335.                         char *t = s;
  336.  
  337.                         while(*t && !isspace((unsigned char)*t))
  338.                             ++t;
  339.  
  340.                         *t = 0;
  341.  
  342.                         char control_byte;
  343.  
  344.                         if (!stricmp(s, "r32")) {
  345.                             control_byte = kTarget_r32;
  346.                         } else if (!stricmp(s, "r16")) {
  347.                             control_byte = kTarget_r16;
  348.                         } else if (!stricmp(s, "r1632")) {
  349.                             control_byte = kTarget_r1632;
  350.                         } else if (!stricmp(s, "r8")) {
  351.                             control_byte = kTarget_r8;
  352.                         } else if (!stricmp(s, "rm")) {
  353.                             control_byte = kTarget_rm;
  354.                         } else if (!stricmp(s, "rx")) {
  355.                             control_byte = kTarget_rx;
  356.                         } else if (!stricmp(s, "rmx")) {
  357.                             control_byte = kTarget_rmx;
  358.                         } else if (!stricmp(s, "rc")) {
  359.                             control_byte = kTarget_rc;
  360.                         } else if (!stricmp(s, "rd")) {
  361.                             control_byte = kTarget_rd;
  362.                         } else if (!stricmp(s, "rs")) {
  363.                             control_byte = kTarget_rs;
  364.                         } else if (!stricmp(s, "rf")) {
  365.                             control_byte = kTarget_rf;
  366.                         } else if (!stricmp(s, "x")) {
  367.                             control_byte = kTarget_x;
  368.                         } else if (!stricmp(s, "hx")) {
  369.                             control_byte = kTarget_hx;
  370.                         } else if (!stricmp(s, "lx")) {
  371.                             control_byte = kTarget_lx;
  372.                         } else if (!stricmp(s, "o")) {
  373.                             control_byte = kTarget_o;
  374.                         } else if (!stricmp(s, "ho")) {
  375.                             control_byte = kTarget_ho;
  376.                         } else if (!stricmp(s, "lo")) {
  377.                             control_byte = kTarget_lo;
  378.                         } else if (!stricmp(s, "a")) {
  379.                             control_byte = kTarget_a;
  380.                         } else if (!stricmp(s, "ha")) {
  381.                             control_byte = kTarget_ha;
  382.                         } else if (!stricmp(s, "la")) {
  383.                             control_byte = kTarget_la;
  384.                         } else if (!stricmp(s, "s")) {
  385.                             control_byte = kTarget_s;
  386.                         } else {
  387.                             oops("unknown macro expansion mode: '%s'\n", s);
  388.                         }
  389.  
  390.                         if (argumentTypeStack[id-1] != (control_byte == kTarget_s))
  391.                             oops("bad argument type: $%d (not a %s)\n", id, argumentTypeStack[id-1] ? "byte" : "string");
  392.  
  393.                         if (firstbit == 0 && lastbit == 2) {
  394.                             r.result += (char)(control_byte + 0x20);
  395.                         } else if (firstbit == 3 && lastbit == 5) {
  396.                             r.result += (char)(control_byte + 0x40);
  397.                         } else if (firstbit != 0 || lastbit != 7) {
  398.                             r.result += (char)(control_byte + 0xe0);
  399.                             r.result += (char)((lastbit+1-firstbit)*16 + firstbit);
  400.                         } else {
  401.                             r.result += (char)control_byte;
  402.                         }
  403.  
  404.                         s = t+1;
  405.                     }
  406.                 } else
  407.                     oops("indecipherable result string\n");
  408.             }
  409.  
  410.             pRuleset->rules.push_back(r);
  411.         }
  412.     }
  413. }
  414.  
  415. #define iterate_forward(type, obj, it) if(0);else for(type::iterator it = (obj).begin(), it##End = (obj).end(); it != it##End; ++it)
  416.  
  417. void *VDDisasmDecompress(void *_dst, const unsigned char *src, int src_len);
  418.  
  419. std::vector<char> ruleTestHeap;
  420.  
  421. void dump_ia(FILE *f) {
  422.     std::vector<char> ruleHeap;
  423.     long decomp_bytes = 0;
  424.     long packed_bytes = 0;
  425.  
  426.     ruleHeap.push_back(g_RuleSystem.size());
  427.  
  428.     iterate_forward(tRuleSystem, g_RuleSystem, it) {
  429.         ruleset& rs = *it;
  430.         std::vector<std::pair<byte, byte> > last_match[4];
  431.         std::string last_result[4];
  432.  
  433.         iterate_forward(std::list<rule>, rs.rules, itRule) {
  434.             rule& r = *itRule;
  435.             std::vector<char>::size_type s, l;
  436.             int prematch, postmatch;
  437.             int i, x, ibest;
  438.             
  439.             l = r.match_stream.size();
  440.  
  441.             ibest = 0;
  442.             prematch = postmatch = 0;
  443.  
  444.             for(i=0; i<4; ++i) {
  445.                 int tprematch = std::mismatch(last_match[i].begin(), last_match[i].end(), r.match_stream.begin()).first - last_match[i].begin();
  446.                 int tpostmatch = std::mismatch(last_match[i].rbegin(), last_match[i].rend(), r.match_stream.rbegin()).first - last_match[i].rbegin();
  447.  
  448.                 if (tprematch+tpostmatch > prematch+postmatch) {
  449.                     prematch = tprematch;
  450.                     postmatch = tpostmatch;
  451.                     ibest = i;
  452.                 }
  453.             }
  454.  
  455.             if (prematch > 7)
  456.                 prematch = 7;
  457.  
  458.             if (postmatch > 7)
  459.                 postmatch = 7;
  460.  
  461.             if (postmatch > l - prematch)
  462.                 postmatch = l - prematch;
  463.  
  464.             ruleHeap.push_back(ibest*64 + postmatch*8 + prematch);
  465.             ruleHeap.push_back(1+l - prematch - postmatch);
  466.  
  467.             for(x=prematch; x<l - postmatch; ++x) {
  468.                 ruleHeap.push_back(r.match_stream[x].first);
  469.                 ruleHeap.push_back(r.match_stream[x].second);
  470.             }
  471.  
  472.             decomp_bytes += l*2+1;
  473.  
  474.             std::rotate(last_match, last_match+3, last_match+4);
  475.             last_match[0] = r.match_stream;
  476.  
  477.             //////////////
  478.  
  479.             l = r.result.size();
  480.  
  481.             ibest = 0;
  482.             prematch = postmatch = 0;
  483.  
  484.             for(i=0; i<4; ++i) {
  485.                 int tprematch = std::mismatch(last_result[i].begin(), last_result[i].end(), r.result.begin()).first - last_result[i].begin();
  486.                 int tpostmatch = std::mismatch(last_result[i].rbegin(), last_result[i].rend(), r.result.rbegin()).first - last_result[i].rbegin();
  487.  
  488.                 if (tprematch+tpostmatch > prematch+postmatch) {
  489.                     prematch = tprematch;
  490.                     postmatch = tpostmatch;
  491.                     ibest = i;
  492.                 }
  493.             }
  494.  
  495.             if (prematch > 7)
  496.                 prematch = 7;
  497.  
  498.             if (postmatch > 7)
  499.                 postmatch = 7;
  500.  
  501.             if (postmatch > l - prematch)
  502.                 postmatch = l - prematch;
  503.  
  504.             ruleHeap.push_back(ibest*64 + postmatch*8 + prematch);
  505.             ruleHeap.push_back(1+l - prematch - postmatch);
  506.             s = ruleHeap.size();
  507.             ruleHeap.resize(s + l - prematch - postmatch);
  508.             std::copy(r.result.begin() + prematch, r.result.begin() + l - postmatch, &ruleHeap[s]);
  509.  
  510.             decomp_bytes += l+1;
  511.  
  512.             std::rotate(last_result, last_result+3, last_result+4);
  513.             last_result[0] = r.result;
  514.         }
  515.  
  516.         ruleHeap.push_back(0);
  517.         ruleHeap.push_back(0);
  518.  
  519.         decomp_bytes += 2;
  520.     }
  521.  
  522.     static const char header[64]="[01|01] VirtualDub disasm module (IA32:P4/Athlon V1.04)\r\n\x1A";
  523.  
  524.     fwrite(header, 64, 1, f);
  525.  
  526.     packed_bytes = ruleHeap.size();
  527.     fwrite(&packed_bytes, 4, 1, f);
  528.  
  529.     decomp_bytes += g_RuleSystem.size() * 4 + 4;
  530.  
  531.     fwrite(&decomp_bytes, 4, 1, f);
  532.  
  533.     fwrite(&ruleHeap[0], packed_bytes, 1, f);
  534.     
  535.     ruleTestHeap.resize(decomp_bytes);
  536.     void *dst_end = VDDisasmDecompress(&ruleTestHeap[0], (const unsigned char *)&ruleHeap[0], packed_bytes);
  537. }
  538.  
  539. ///////////////////////////////////////////////////////////////////////
  540.  
  541. struct VDDisassemblyContext {
  542.     const unsigned char **pRuleSystem;
  543.     long (*pSymLookup)(unsigned long virtAddr, char *buf, int buf_len);
  544.  
  545.     bool bSizeOverride;            // 66
  546.     bool bAddressOverride;        // 67
  547.     bool bRepnePrefix;            // F2
  548.     bool bRepePrefix;            // F3
  549.     const char *pszSegmentOverride;
  550.  
  551.     long    physToVirtOffset;
  552.  
  553.     char    heap[2048];
  554.     int        stack[32];
  555. };
  556.  
  557. char *apply_ruleset(VDDisassemblyContext *pContext, const ruleset *rs, int *sp, char *hp, const byte *source, int bytes, const byte *&source_end);
  558. char *VDDisasmMatchRule(VDDisassemblyContext *pContext, const unsigned char *source, const unsigned char *pattern, int pattern_len, int bytes, int *sp, char *hp, const unsigned char *&source_end);
  559.  
  560. void *VDDisasmDecompress(void *_dst, const unsigned char *src, int src_len) {
  561.     const unsigned char *src_limit = src + src_len;
  562.     unsigned char *dst = (unsigned char *)_dst;
  563.  
  564.     // read ruleset count
  565.     int rulesets = *src++;
  566.     unsigned char **prstab = (unsigned char **)dst;
  567.  
  568.     dst += sizeof(unsigned char *) * (rulesets + 1);
  569.  
  570.     // decompress rulesets sequentially
  571.     for(int rs=0; rs<rulesets; ++rs) {
  572.         prstab[rs+1] = dst;
  573.  
  574.         const unsigned char *pattern_cache[4][2];
  575.         const unsigned char *result_cache[4][2];
  576.  
  577.         while(src[0] || src[1]) {
  578.             unsigned char packctl;
  579.             int packsrc, cnt;
  580.  
  581.             // read pack control byte and copy prematch-literal-postmatch for pattern
  582.             packctl = *src++;
  583.             packsrc = packctl >> 6;
  584.  
  585.             int prematch = (packctl & 7) * 2;
  586.             int postmatch = ((packctl>>3) & 7) * 2;
  587.             int literal = (*src++ - 1) * 2;
  588.  
  589.             *dst++ = literal + prematch + postmatch;
  590.  
  591.             const unsigned char *pattern_start = dst;
  592.  
  593.             for(cnt=0; cnt<prematch; ++cnt)
  594.                 *dst++ = pattern_cache[packsrc][0][cnt];
  595.  
  596.             for(cnt=0; cnt<literal; ++cnt)
  597.                 *dst++ = *src++;
  598.  
  599.             for(cnt=0; cnt<postmatch; ++cnt)
  600.                 *dst++ = pattern_cache[packsrc][1][cnt-postmatch];
  601.  
  602.             // cycle pattern cache
  603.  
  604.             for(cnt=3; cnt>0; --cnt) {
  605.                 pattern_cache[cnt][0] = pattern_cache[cnt-1][0];
  606.                 pattern_cache[cnt][1] = pattern_cache[cnt-1][1];
  607.             }
  608.  
  609.             pattern_cache[0][0] = pattern_start;
  610.             pattern_cache[0][1] = dst;
  611.  
  612.             // read pack control byte and copy prematch-literal-postmatch for result
  613.  
  614.             packctl = *src++;
  615.             packsrc = packctl >> 6;
  616.  
  617.             prematch = (packctl & 7);
  618.             postmatch = ((packctl>>3) & 7);
  619.             literal = (*src++ - 1);
  620.  
  621.             *dst++ = prematch + postmatch + literal;
  622.  
  623.             const unsigned char *result_start = dst;
  624.  
  625.             for(cnt=0; cnt<prematch; ++cnt)
  626.                 *dst++ = result_cache[packsrc][0][cnt];
  627.  
  628.             for(cnt=0; cnt<literal; ++cnt)
  629.                 *dst++ = *src++;
  630.  
  631.             for(cnt=0; cnt<postmatch; ++cnt)
  632.                 *dst++ = result_cache[packsrc][1][cnt-postmatch];
  633.  
  634.             // cycle result cache
  635.  
  636.             for(cnt=3; cnt>0; --cnt) {
  637.                 result_cache[cnt][0] = result_cache[cnt-1][0];
  638.                 result_cache[cnt][1] = result_cache[cnt-1][1];
  639.             }
  640.  
  641.             result_cache[0][0] = result_start;
  642.             result_cache[0][1] = dst;
  643.         }
  644.  
  645.         src += 2;
  646.  
  647.         *dst++ = 0;
  648.         *dst++ = 0;
  649.     }
  650.  
  651.     prstab[0] = prstab[rulesets];
  652.  
  653.     return dst;
  654. }
  655.  
  656. long VDDisasmPack32(const int *src) {
  657.     return src[0] + (src[1]<<8) + (src[2]<<16) + (src[3]<<24);
  658. }
  659.  
  660. void VDDisasmExpandRule(VDDisassemblyContext *pContext, char *s, const unsigned char *result, const int *sp_base, const unsigned char *source) {
  661.     static const char *const reg32[8]={"eax","ecx","edx","ebx","esp","ebp","esi","edi"};
  662.     static const char *const reg16[8]={"ax","cx","dx","bx","sp","bp","si","di"};
  663.     static const char *const reg8[8]={"al","cl","dl","bl","ah","ch","dh","bh"};
  664.     static const char *const regmmx[8]={"mm0","mm1","mm2","mm3","mm4","mm5","mm6","mm7"};
  665.     static const char *const regxmm[8]={"xmm0","xmm1","xmm2","xmm3","xmm4","xmm5","xmm6","xmm7"};
  666.     static const char *const regcrn[8]={"cr0","cr1","cr2","cr3","cr4","cr5","cr6","cr7"};
  667.     static const char *const regdrn[8]={"dr0","dr1","dr2","dr3","dr4","dr5","dr6","dr7"};
  668.     static const char *const regseg[8]={"es","cs","ss","ds","fs","gs","?6s","?7s"};
  669.     static const char *const regf[8]={"st(0)","st(1)","st(2)","st(3)","st(4)","st(5)","st(6)","st(7)"};
  670.  
  671.     static const char *const *const sStaticLabels[]={
  672.         reg32,
  673.         reg16,
  674.         reg8,
  675.         regmmx,
  676.         regxmm,
  677.         regcrn,
  678.         regdrn,
  679.         regseg,
  680.         regf
  681.     };
  682.  
  683.     const unsigned char *result_limit = result + result[0]+1;
  684.  
  685.     ++result;
  686.  
  687.     while(result < result_limit) {
  688.         char c = *result++;
  689.  
  690.         if ((unsigned char)(c&0x7f) < 32) {
  691.             if (c & 0x80) {
  692.                 c &= 0x7f;
  693.                 *s++ = ' ';
  694.             }
  695.  
  696.             static const unsigned char static_bitfields[8]={
  697.                 0x80, 0x30, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00
  698.             };
  699.  
  700.             unsigned char control_byte = (unsigned char)*result++;
  701.             unsigned char bitfield = static_bitfields[control_byte >> 5];
  702.  
  703.             if (!bitfield)
  704.                 bitfield = (unsigned char)*result++;
  705.  
  706.             int bf_start = bitfield & 15;
  707.             int bf_siz = bitfield>>4;
  708.             const char *arg_s = (const char *)sp_base[c-1];
  709.             int arg = (sp_base[c-1] >> bf_start) & ((1<<bf_siz)-1);
  710.  
  711.             control_byte &= 0x1f;
  712.  
  713.             if (control_byte < 10) {
  714.                 s = strtack(s, sStaticLabels[control_byte-1][arg]);
  715.             } else {
  716.                 long symoffset = 0;
  717.  
  718.                 switch(control_byte) {
  719.                 case kTarget_r1632:
  720.                     s = strtack(s, reg32[arg] + pContext->bSizeOverride);
  721.                     break;
  722.                 case kTarget_rmx:
  723.                     s = strtack(s, (pContext->bSizeOverride ? regxmm : regmmx)[arg]);
  724.                     break;
  725.                 case kTarget_lx:
  726.                     symoffset = VDDisasmPack32(sp_base + c - 1);
  727.                     s += sprintf(s, "%08lx", symoffset);
  728.                     break;
  729.                 case kTarget_hx:
  730.                     s += sprintf(s, "%02x%02x"
  731.                                 , (unsigned char)sp_base[c]
  732.                                 , (unsigned char)sp_base[c-1]
  733.                                 );
  734.                     break;
  735.                 case kTarget_x:
  736.                     s += sprintf(s, "%02x", arg);
  737.                     break;
  738.                 case kTarget_lo:
  739.                     symoffset = VDDisasmPack32(sp_base + c - 1);
  740.                     s += sprintf(s, "%c%02lx", symoffset<0 ? '-' : '+', abs(symoffset));
  741.                     break;
  742.                 case kTarget_ho:
  743.                     {
  744.                         short x =  ((unsigned char)sp_base[c  ] << 8)
  745.                                 +  (unsigned char)sp_base[c-1];
  746.  
  747.                         s += sprintf(s, "%c%02lx", x<0 ? '-' : '+', abs(x));
  748.                     }
  749.                     break;
  750.                 case kTarget_o:
  751.                     s += sprintf(s, "%c%02x", arg&0x80?'-':'+', abs((signed char)arg));
  752.                     break;
  753.                 case kTarget_la:
  754.                     symoffset = (long)source + VDDisasmPack32(sp_base + c - 1) + pContext->physToVirtOffset;
  755.                     s += sprintf(s, "%08lx", symoffset);
  756.                     break;
  757.                 case kTarget_ha:
  758.                     symoffset = (long)source + (signed short)(sp_base[c-1] + (sp_base[c]<<8)) + pContext->physToVirtOffset;
  759.                     s += sprintf(s, "%08lx", symoffset);
  760.                     break;
  761.                 case kTarget_a:
  762.                     symoffset = (long)source + (signed char)arg + pContext->physToVirtOffset;
  763.                     s += sprintf(s, "%08lx", symoffset);
  764.                     break;
  765.                 case kTarget_s:
  766.                     s = strtack(s, arg_s);
  767.                     break;
  768.                 }
  769.  
  770.                 if (symoffset && pContext->pSymLookup) {
  771.                     symoffset = pContext->pSymLookup((unsigned long)symoffset, s+2, 128);
  772.  
  773.                     if (symoffset >= 0) {
  774.                         s[0] = ' ';
  775.                         s[1] = '(';
  776.                         s += 2;
  777.                         while(*s)
  778.                             ++s;
  779.                         if (symoffset)
  780.                             s += sprintf(s, "+%02x", symoffset);
  781.                         *s++ = ')';
  782.                     }
  783.                 }
  784.             }
  785.         } else if ((unsigned char)c >= 0xe0) {
  786.             switch(c) {
  787.             case kTarget_ap:
  788.                 if (pContext->pszSegmentOverride) {
  789.                     s = strtack(s, pContext->pszSegmentOverride);
  790.                     *s++ = ':';
  791.                 }
  792.                 break;
  793.             case kTarget_p_cs:    pContext->pszSegmentOverride = regseg[1];    break;
  794.             case kTarget_p_ss:    pContext->pszSegmentOverride = regseg[2];    break;
  795.             case kTarget_p_ds:    pContext->pszSegmentOverride = regseg[3];    break;
  796.             case kTarget_p_es:    pContext->pszSegmentOverride = regseg[0];    break;
  797.             case kTarget_p_fs:    pContext->pszSegmentOverride = regseg[4];    break;
  798.             case kTarget_p_gs:    pContext->pszSegmentOverride = regseg[5];    break;
  799.             case kTarget_p_66:    pContext->bSizeOverride = true;                break;
  800.             case kTarget_p_67:    pContext->bAddressOverride = true;            break;
  801.             case kTarget_p_F2:    pContext->bRepnePrefix = true;                break;
  802.             case kTarget_p_F3:    pContext->bRepePrefix = true;                break;
  803.             }
  804.         } else
  805.             *s++ = c;
  806.     }
  807.  
  808.     *s = 0;
  809. }
  810.  
  811. char *VDDisasmApplyRuleset(VDDisassemblyContext *pContext, const unsigned char *rs, int *sp, char *hp, const unsigned char *source, int bytes, const byte *&source_end) {
  812.     char *hpr;
  813.  
  814.     while(rs[0] || rs[1]) {
  815.         const unsigned char *src_end;
  816.         const unsigned char *result = rs + rs[0] + 1;
  817.         const unsigned char *match_next = result + result[0] + 1;
  818.  
  819.         hpr = VDDisasmMatchRule(pContext, source, rs+1, rs[0]>>1, bytes, sp, hp, src_end);
  820.  
  821.         if (hpr) {
  822.             VDDisasmExpandRule(pContext, hpr, result, sp, src_end);
  823.  
  824.             source_end = src_end;
  825.             return hpr;
  826.         }
  827.  
  828.         rs = match_next;
  829.     }
  830.  
  831.     return NULL;
  832. }
  833.  
  834. char *VDDisasmMatchRule(VDDisassemblyContext *pContext, const unsigned char *source, const unsigned char *pattern, int pattern_len, int bytes, int *sp, char *hp, const unsigned char *&source_end) {
  835.     while(bytes && pattern_len) {
  836.         if (!pattern[1] && pattern[0]) {
  837.             if (pattern[0] & 0x80) {
  838.                 int count = pattern[0] & 0x3f;
  839.  
  840.                 if (pattern[0] & 0x40)
  841.                     --source;
  842.             
  843.                 const byte *src_end;
  844.  
  845.                 hp = VDDisasmApplyRuleset(pContext, pContext->pRuleSystem[count+1], sp, hp, source, bytes, src_end);
  846.  
  847.                 if (!hp)
  848.                     return NULL;
  849.  
  850.                 *sp++ = *source;
  851.                 *sp++ = (int)hp;
  852.  
  853.                 while(*hp++);
  854.  
  855.                 source = src_end;
  856.             } else if (pattern[0] < 16) {
  857.                 if (pattern[0] > bytes)
  858.                     return NULL;
  859.  
  860.                 for(int i=0; i<pattern[0]; ++i) {
  861.                     *sp++ = *source++;
  862.                 }
  863.  
  864.                 bytes -= pattern[0]-1;
  865.             } else {
  866.                 switch(pattern[0]) {
  867.                 case 16:    if (!pContext->bSizeOverride)        return NULL;    break;
  868.                 case 17:    if (!pContext->bAddressOverride)    return NULL;    break;
  869.                 case 18:    if (!pContext->bRepnePrefix)        return NULL;    break;
  870.                 case 19:    if (!pContext->bRepePrefix)            return NULL;    break;
  871.                 case 20:    if (pContext->pszSegmentOverride)    return NULL;    break;
  872.                 }
  873.             }
  874.         } else {
  875.             byte b = *source++;
  876.  
  877.             if ((b & pattern[1]) != pattern[0])
  878.                 return NULL;
  879.  
  880.             *sp++ = b;
  881.         }
  882.         pattern += 2;
  883.         --bytes;
  884.         --pattern_len;
  885.     }
  886.  
  887.     if (!pattern_len) {
  888.         source_end = source;
  889.         return hp;
  890.     }
  891.  
  892.     return NULL;
  893. }
  894.  
  895. void VDDisassemble(VDDisassemblyContext *pvdc, const byte *source, int bytes) {
  896.     while(bytes > 0) {
  897.         const byte *src2 = source;
  898.         const byte *src_end;
  899.         char *s;
  900.  
  901.         pvdc->bAddressOverride = false;
  902.         pvdc->bSizeOverride = false;
  903.         pvdc->bRepePrefix = false;
  904.         pvdc->bRepnePrefix = false;
  905.         pvdc->pszSegmentOverride = NULL;
  906.  
  907.         do {
  908.             s = VDDisasmApplyRuleset(pvdc, pvdc->pRuleSystem[0], pvdc->stack, pvdc->heap, src2, bytes, src_end);
  909.  
  910.             bytes -= (src_end - src2);
  911.             src2 = src_end;
  912.         } while(!*s && bytes);
  913.  
  914.         if (!bytes)
  915.             break;
  916.  
  917.         int count = src_end - source;
  918.         int linecnt;
  919.  
  920.         printf("%08lx:", (unsigned long)source + pvdc->physToVirtOffset);
  921.  
  922.         for(linecnt=0; linecnt<7 && source < src_end; ++linecnt)
  923.             printf(" %02x", (unsigned char)*source++);
  924.  
  925.         char *t = s;
  926.         while(*t && *t != ' ')
  927.             ++t;
  928.  
  929.         if (*t)
  930.             *t++ = 0;
  931.  
  932.         printf("%*c%-7s%s\n", 2 + 3*(7-linecnt), ' ', s, t);
  933.  
  934.         // flush remaining bytes
  935.  
  936.         while(source < src_end) {
  937.             printf("         ");
  938.             for(linecnt=0; linecnt<7 && source < src_end; ++linecnt)
  939.                 printf(" %02x", (unsigned char)*source++);
  940.             putchar('\n');
  941.         }
  942.  
  943.         bytes -= count;
  944.     }
  945. }
  946.  
  947. ///////////////////////////////////////////////////////////////////////////
  948.  
  949. void __declspec(naked) test1() {
  950.     __asm {
  951.         __emit 0x0f
  952.         __emit 0x18
  953.         __emit 0x05
  954.         __emit 0x40
  955.         __emit 0x07
  956.         __emit 0x90
  957.         __emit 0x02
  958.  
  959.         prefetchnta [eax]
  960.         prefetcht0 [eax]
  961.         prefetcht1 [eax]
  962.         prefetcht2 [eax]
  963.  
  964.         pavgusb        mm0,[eax]
  965.         prefetch    [eax]
  966.         prefetchw    [eax]
  967.         pswapd        mm1, mm0
  968.         push        [eax]
  969.         push        word ptr [eax]
  970.  
  971.         cvtsi2ss    xmm4, ecx
  972.         cvtsi2ss    xmm4, [ecx]
  973.         cvtpi2ps    xmm4, mm2
  974.         cvtpi2ps    xmm4, [ecx]
  975.  
  976.         cvtss2si    eax, xmm4
  977.         cvtss2si    eax, [ecx]
  978.         cvtps2pi    mm2, xmm4
  979.         cvtps2pi    mm2, [ecx]
  980.  
  981.         cvttss2si    eax, xmm4
  982.         cvttss2si    eax, [ecx]
  983.         cvttps2pi    mm2, xmm4
  984.         cvttps2pi    mm2, [ecx]
  985.  
  986.         cvtsi2sd    xmm4, ecx
  987.         cvtsi2sd    xmm4, [ecx]
  988.         cvtpi2pd    xmm4, mm2
  989.         cvtpi2pd    xmm4, [ecx]
  990.  
  991.         cvtsd2si    eax, xmm4
  992.         cvtsd2si    eax, [ecx]
  993.         cvtpd2pi    mm2, xmm4
  994.         cvtpd2pi    mm2, [ecx]
  995.  
  996.         cvttsd2si    eax, xmm4
  997.         cvttsd2si    eax, [ecx]
  998.         cvttpd2pi    mm2, xmm4
  999.         cvttpd2pi    mm2, [ecx]
  1000.  
  1001.         movq        xmm0, qword ptr [eax]
  1002.  
  1003. __emit 0x66
  1004. __emit 0x0f
  1005. __emit 0x6f
  1006. __emit 0x2d
  1007. __emit 0xf0
  1008. __emit 0x42
  1009. __emit 0x0e
  1010. __emit 0x10
  1011.  
  1012.         rep movsw
  1013.         lock rep movs es:word ptr [edi], cs:word ptr [esi]
  1014.  
  1015.         lock mov cs:dword ptr [eax+ecx*4+12300000h], 12345678h
  1016.  
  1017.         __emit 0x2e
  1018.         jc x1
  1019.  
  1020.         __emit 0x3e
  1021.         jc y1
  1022.  
  1023.         call esi
  1024.  
  1025.         shl ecx,1
  1026.  
  1027.         ret
  1028. x1:
  1029. y1:
  1030.         nop
  1031.  
  1032.         fldcw word ptr [esp]
  1033.  
  1034.     }
  1035. }
  1036.  
  1037. ///////////////////////////////////////////////////////////////////////////
  1038.  
  1039. long symLookup(unsigned long virtAddr, char *buf, int buf_len) {
  1040.     unsigned long offs;
  1041.  
  1042.     if ((offs = (virtAddr - (unsigned long)symLookup)) < 256) {
  1043.         strcpy(buf, "symLookup");
  1044.         return (long)offs;
  1045.     }
  1046.  
  1047.     if ((offs = (virtAddr - (unsigned long)VDDisassemble)) < 256) {
  1048.         strcpy(buf, "VDDisassemble");
  1049.         return (long)offs;
  1050.     }
  1051.  
  1052.     if ((offs = (virtAddr - (unsigned long)VDDisasmApplyRuleset)) < 256) {
  1053.         strcpy(buf, "VDDisasmApplyRuleset");
  1054.         return (long)offs;
  1055.     }
  1056.  
  1057.     if ((offs = (virtAddr - (unsigned long)printf)) < 16) {
  1058.         strcpy(buf, "printf");
  1059.         return (long)offs;
  1060.     }
  1061.  
  1062.     return -1;
  1063. }
  1064.  
  1065. int main(int argc, char **argv) {
  1066.     FILE *f = fopen(argc>1?argv[1]:"ia32.txt", "r");
  1067.     parse_ia(f);
  1068.     fclose(f);
  1069.  
  1070.     f = fopen(argc>2?argv[2]:"ia32.bin", "wb");
  1071.     dump_ia(f);
  1072.     fclose(f);
  1073.  
  1074. //    disassemble((const byte *)&parse_ia, 2048);
  1075. //    disassemble((const byte *)&test1, 300);
  1076.  
  1077.     VDDisassemblyContext vdc;
  1078.  
  1079.     vdc.pRuleSystem = (const unsigned char **)&ruleTestHeap[0];
  1080.     vdc.pSymLookup = symLookup;
  1081.     vdc.physToVirtOffset = 0;
  1082.  
  1083.     VDDisassemble(&vdc, (const byte *)&test1, 1024);
  1084. //    VDDisassemble(&vdc, (const byte *)&VDDisassemble, 1024);
  1085.  
  1086.     getch();
  1087.  
  1088.     return 0;
  1089. }
  1090.